<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Flow control in Tcl</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Tcl, learn Tcl, language, flow control, if, else, while, for, foreach, language, Linux">
<meta name="description" content="This chapter of the Tcl tutorial covers flow control.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Flow control in Tcl</h1>

<p>
In this part of the Tcl tutorial, we will talk about the flow control.
We will define several commands that enable us to control the flow of 
a Tcl script. 
</p>

<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* LargeSquare */
google_ad_slot = "5070696322";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>

<p>
In Tcl language there are several commands that are used
to alter the flow of the program. When the program is run, the commands 
are executed from the top of the source file to the bottom. One by one. 
This flow can be altered by specific commands. Commands can be executed
multiple times. Some commands are conditional. They
are executed only if a specific condition is met. 
</p>

<h2>The if command</h2>

<p>
The <code>if</code> command has the following general form:
</p>

<pre>
if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
</pre>

<p>
The <code>if</code> command is used to check if an expression 
is true. If it is true, a body of command(s) is then executed. 
The body is enclosed by curly brackets.
</p>

<p>
The if command evaluates an expression. The expression must return 
a boolean value. In Tcl, 1, yes, true mean true and 0, no, false mean
false. 
</p>

<pre class="code">
!/usr/bin/tclsh

if yes {
    puts "This message is always shown"
}
</pre>

<p>
In the above example, the body enclosed by { } characters is always 
executed. 
</p>

<pre class="code">
#!/usr/bin/tclsh

if true then {
    puts "This message is always shown"
}
</pre>

<p>
The <code>then</code> command is optional. We can use it if we think, it
will make the code more clear. 
</p>


<hr class="btm">

<p>
We can use the <code>else</code> command to create a simple branch. 
If the expression inside the square brackets following the if command 
evaluates to false, the command following the <code>else</code> 
command is automatically executed. 
</p>

<pre class="code">
#!/usr/bin/tclsh

set sex female

if {$sex == "male"} {

    puts "It is a boy"
} else {

    puts "It is a girl"
}
</pre>

<p>
We have a sex variable. It has "female" string. The boolean expression 
evaluates to false and we get "It is a girl" in the console.  
</p>

<pre>
$ ./girlboy.tcl 
It is a girl
</pre>


<p>
We can create multiple branches using the <code>elseif</code> command.
The <code>elseif</code> command tests for another condition, if and only if 
the previous condition was not met. Note, that we can use multiple 
<code>elseif</code> commands in our tests.
</p>

<pre class="code">
#!/usr/bin/tclsh

# nums.tcl

puts -nonewline "Enter a number: "
flush stdout
set a [gets stdin]

if {$a &lt; 0} {

    puts "the number is negative"
} elseif { $a == 0 } {

    puts "the numer is zero"
} else {

    puts "the number is positive"
}
</pre>

<p>
In the above script we have a prompt to enter a value. We test the value.
If it is a negative number or positive or if it equals to zero. If the first 
expression evaluates to false, the second expression is evaluated. 
If the previous conditions were not met, than the body following the 
<code>else</code> command would be executed.
</p>

<pre>
$ ./nums.tcl 
Enter a number: 2
the number is positive
$ ./nums.tcl 
Enter a number: 0
the numer is zero
$ ./nums.tcl 
Enter a number: -3
the number is negative
</pre>

<p>
Running the example multiple times. 
</p>

<h2>The switch command</h2>

<p>
The <code>switch</code> command matches its string argument against each of the pattern 
arguments in order. As soon as it finds a pattern that matches string it 
evaluates the following body argument by passing it recursively to the Tcl 
interpreter and returns the result of that evaluation. If the last pattern 
argument is default then it matches anything. If no pattern argument matches 
string and no default is given, then the switch command returns an empty string.
</p>

<pre class="code">
#!/usr/bin/tclsh                                                                                              
                                                                                                              
puts -nonewline "Select a top level domain name "
flush stdout                                                                                                  
                                                                                                              
gets stdin domain                                                                                             
                                                                                                              
switch $domain {                                                                                              
    
    us { puts "United States" }                                                                               
    de { puts Germany }                                                                                       
    sk { puts Slovakia }                                                                                      
    hu { puts Hungary }
    default { puts unknown }                                                                                
}
</pre>

<p>
In our script, we prompt for a domain name. There are several options. If the value 
equals for example to us the "United States" string is printed to the console. 
If the value does not match to any given value, the default body is executed and
unknown is printed to the console. 
</p>

<pre>
$ ./switch.tcl 
Select a top level domain name sk
Slovakia
</pre>

<p>
We have entered sk string to the console and the program responded with Slovakia.
</p>



<h2>The while command</h2>

<p>
The <code>while</code> command is a control flow command 
that allows code to be executed repeatedly based on a given boolean condition. 
</p>

<p>
The <code>while</code> command executes the commands inside the
block enclosed by the curly brackets. The commands are executed each time 
the expression is evaluated to true. 
</p>

<pre class="code">
#!/usr/bin/tclsh

# whileloop.tcl

set i 0
set sum 0

while { $i &lt; 10 } {

    incr i
    incr sum $i
}

puts $sum
</pre>

<p>
In the code example, we calculate the sum of values from a range of numbers.
</p>

<p>
The <code>while</code> loop has three parts. Initialization, testing and 
updating. Each execution of the command is called a cycle. 
</p>

<pre class="explanation">
set i 0
</pre>

<p>
We initiate the i variable. It is used as a counter.
</p>

<pre class="explanation">
while { $i &lt; 10 } {

...
}
</pre>

<p>
The expression inside the square brackets following the <code>while</code>
command is the second phase, the testing. The commands in the body are 
executed, until the expression is evaluated to false. 
</p>

<pre class="explanation">
incr i
</pre>

<p>
The last, third phase of the <code>while</code> loop. The updating. We increment
the counter. Note that improper handling of the <code>while</code> loops may lead
to endless cycles. 
</p>



<h2>The for command</h2>

<p>
When the number of cycles is know before the loop is initiated, 
we can use the <code>for</code> command. In this construct 
we declare a counter variable, which is automatically increased 
or decreased in value during each repetition of the loop.
</p>


<pre class="code">
#!/usr/bin/tclsh

for {set i 0} {$i &lt; 10} {incr i} {
    puts $i
}
</pre>

<p>
In this example, we print numbers 0..9 to the console. 
</p>

<pre class="explanation">
for {set i 0} {$i &lt; 10} {incr i} {
    puts $i
}
</pre>

<p>
There are three phases. First, we initiate the counter i to zero.
This phase is done only once. Next comes the condition. If the 
condition is met, the command inside the for block is executed.
Then comes the third phase; the counter is increased. Now we repeat
the 2, 3 phases until the condition is not met and the for loop
is left. In our case, when the counter i is equal to 10, the for loop
stops executing.
</p>


<h2>The foreach command</h2>

<p>
The <code>foreach</code> command simplifies traversing over 
collections of data. It has no explicit counter. The <code>foreach</code> 
command goes throught the list one by one and 
the current value is copied to a variable defined in the construct.
</p>

<pre class="code">
#!/usr/bin/tclsh

set planets { Mercury Venus Earth Mars Jupiter Saturn
    Uranus Neptune }

foreach planet $planets {
    puts $planet
}
</pre>

<p>
In this example, we use the <code>foreach</code> command to go
through a list of planets. 
</p>

<pre class="explanation">
foreach planet $planets {
    puts $planet
}
</pre>

<p>
The usage of the <code>foreach</code> command is straightforward.
The planets is the list, that we iterate through. The planet is the
temporary variable, that has the current value from the list. 
The <code>foreach</code> command goes through all the planets 
and prints them to the console. 
</p>

<pre>
$ ./planets.tcl 
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
</pre>

<p>
Running the above Tcl script gives this output.
</p>

<hr class="btm">

<pre class="code">
#!/usr/bin/tclsh

set actresses { Rachel Weiss Scarlett Johansson Jessica Alba \
    Marion Cotillard Jennifer Connelly}

foreach {first second} $actresses {
    puts "$first $second"
}
</pre>

<p>
In this script, we iterate througn pairs of values of a list.
</p>

<pre class="explanation">
foreach {first second} $actresses {
    puts "$first $second"
}
</pre>

<p>
We pick two values from the list at each iteration. 
</p>

<pre>
$ ./actresses.tcl 
Rachel Weiss
Scarlett Johansson
Jessica Alba
Marion Cotillard
Jennifer Connelly
</pre>

<p>
Output of actresses.tcl.
</p>


<hr class="btm">


<pre class="code">
#!/usr/bin/tclsh

foreach i { one two three } item {car coins rocks} {
    puts "$i $item"
}
</pre>

<p>
We can iterate over two lists in parallel. 
</p>

<pre>
$ ./parallel.tcl 
one car
two coins
three rocks
</pre>

<p>
Output.
</p>

<h2>The break, continue commands</h2>

<p>
The <code>break</code> command can be used to terminate 
a block defined by <code>while</code>, <code>for</code>
or <code>switch</code> commands.
</p>

<pre class="code">
#!/usr/bin/tclsh

while true {

    set r [expr 1 + round(rand()*30)]
    puts -nonewline "$r "

    if {$r == 22} { break }
}

puts ""
</pre>

<p>
We define an endless <code>while</code> loop. We use the <code>break</code> 
command to get out of this loop. We choose a random value from 1 to 30. 
We print the value. If the value equals to 22, we finish the endless while loop. 
</p>

<pre class="explanation">
set r [expr 1 + round(rand()*30)]
</pre>

<p>
Here we calculate a random number between 1..30. The <code>rand()</code> is a built-in
Tcl procedure. It returns a random number from 0 to 0.99999. 
The <code>rand()*30</code> returns a random number between 0 to 29.99999.
The <code>round()</code> procedure rounds the final number.
</p>

<pre>
$ ./breakcommand.tcl 
28 20 8 8 12 22 
</pre>

<p>
We might get something like this.
</p>

<hr class="btm">

<p>
The <code>continue</code> command is used to skip a
part of the loop and continue with the next iteration of the loop.
It can be used in combination with <code>for</code> and 
<code>while</code> commands. 
</p>

<p>
In the following example, we will print a list of numbers, 
that cannot be divided by 2 without a remainder. 
</p>

<pre class="code">
#!/usr/bin/tclsh

set num 0

while { $num &lt; 100 } {

    incr num

    if {$num % 2 == 0} { continue }
 
    puts "$num "
}

puts ""
</pre>

<p>
We iterate through numbers 1..99 with the <code>while</code> loop.
</p>

<pre class="explanation">
if {$num % 2 == 0} { continue }
</pre>

<p>
If the expression num % 2 returns 0, the number in question can be divided by 2.
The <code>continue</code> command is executed and the rest of the cycle is skipped.
In our case, the last command of the loop is skipped and the number is not printed to the
console. The next iteration is started. 
</p>


<p>
In this part of the Tcl tutorial, we were talking about control 
flow structures. 
</p>

<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified April 9, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
